﻿using System;
using System.Linq;
using System.Web.Mvc;
using Umbraco.Cms.Web.Context;

using Umbraco.Framework;
using Umbraco.Framework.Persistence.Model;
using Umbraco.Framework.Persistence.Model.Constants;
using Umbraco.Framework.Persistence.Model.IO;
using Umbraco.Hive;
using Umbraco.Hive.ProviderGrouping;
using Umbraco.Hive.RepositoryTypes;
using Umbraco.Cms.Web;

namespace idseefeld.com.imagecropper
{
	public static class UmbracoMediaHelper
	{
		#region backoffice methods without UrlHelper
		private const string DEFAULT_MEDIA_IMAGE_UPLOADER_ALIAS = "uploadedFile";
		public static string GetMediaUrl(HiveId id, string propertyAlias)
		{
			return GetMediaUrl(id, propertyAlias, "", 0, DEFAULT_MEDIA_IMAGE_UPLOADER_ALIAS);
		}
		public static string GetMediaUrl(HiveId id, string propertyAlias, int size)
		{
			return GetMediaUrl(id, propertyAlias, "", size, DEFAULT_MEDIA_IMAGE_UPLOADER_ALIAS);
		}
		public static string GetMediaUrl(HiveId id, string propertyAlias, int size, string imageUploaderProperty)
		{
			return GetMediaUrl(id, propertyAlias, "", size, imageUploaderProperty);
		}
		public static string GetMediaUrl(HiveId id, string propertyAlias, string cropName, int size, string imageUploaderProperty)
		{
			var item = UmbracoHelper.GetEntiyByHiveId(id);

			if (item == null) return null;

			return GetMediaUrl(item, propertyAlias, cropName, size);
		}
		public static string GetMediaUrl(TypedEntity entity, string propertyAlias, string cropName, int size)
		{
			return GetMediaUrl(entity, propertyAlias, cropName, size, DEFAULT_MEDIA_IMAGE_UPLOADER_ALIAS);
		}
		public static string GetMediaUrl(TypedEntity entity, string propertyAlias, string cropName, int size, string imageUploaderProperty)
		{
			//TODO: There is a lot of duplication between this and the MediaProxyController (with slight differences). Need to find a way to reuse code.

			var appContext = DependencyResolver.Current.GetService<IUmbracoApplicationContext>();
			using (var securityUow = appContext.Hive.OpenReader<ISecurityStore>()) {
				// Check to see if anonymous view is allowed
				var anonymousViewAllowed = !appContext.Security.PublicAccess.IsProtected(entity.Id);

				// Get upload property
				var prop = propertyAlias.IsNullOrWhiteSpace()
					? entity.Attributes.SingleOrDefault(x => x.AttributeDefinition.AttributeType.RenderTypeProvider.InvariantEquals(CorePluginConstants.FileUploadPropertyEditorId))
					: entity.Attributes.SingleOrDefault(x => x.AttributeDefinition.Alias == propertyAlias);

				if (prop == null)// || (!prop.Values.ContainsKey("MediaId") && !prop.Values.GetValueAsString().StartsWith("media")))
					return null; // Couldn't find property so return null

				if (!prop.Values.ContainsKey("MediaId")) {
					//this might by a Media reference from a Media Picker, thus get the media items MediaId
					string mediaItemId = prop.Values["Value"].ToString();

					if (mediaItemId.StartsWith("media")) {
						string result = null;
						try {
							result = GetMediaUrl(HiveId.Parse(mediaItemId), imageUploaderProperty, cropName, size, DEFAULT_MEDIA_IMAGE_UPLOADER_ALIAS);
						}
						catch { }
						return result;
					}
					else {
						//other types are not support
						return null;
					}
				}

				var mediaId = prop.Values["MediaId"].ToString();
				var fileId = new HiveId(prop.Values["Value"].ToString());

				// Get the file
				using (var fileUow = appContext.Hive.OpenReader<IFileStore>(fileId.ToUri())) {
					var file = fileUow.Repositories.Get<File>(fileId);

					if (file == null)
						return null; // Couldn't find file so return null

					// Fetch the thumbnail
					string sizeName = (size > 0 && String.IsNullOrEmpty(cropName)) ? size.ToString() : cropName;
					if (!String.IsNullOrEmpty(sizeName)) {
						var relation = fileUow.Repositories.GetLazyChildRelations(fileId, FixedRelationTypes.ThumbnailRelationType)
								.SingleOrDefault(x => x.MetaData.Single(y => y.Key == "size").Value == sizeName);

						file = (relation != null && relation.Destination != null)
							? (File)relation.Destination
							: null;
					}
					if (file == null)
						return null; // Couldn't find file so return null

					return file.PublicUrl;

				}
			}
		}
		#endregion

		#region extension method for UrlHelper
		public static string GetMediaUrl(this UrlHelper url, HiveId id, string propertyAlias, int size, string cropName)
		{
			return url.GetMediaUrl(id, propertyAlias, cropName, size);
		}
		public static string GetMediaUrl(this UrlHelper url, HiveId id, string propertyAlias, string cropName)
		{
			return url.GetMediaUrl(id, propertyAlias, cropName, 0);
		}
		public static string GetMediaUrl(this UrlHelper url, HiveId id, string propertyAlias, string cropName, int size)
		{
			var item = UmbracoHelper.GetEntiyByHiveId(id);

			if (item == null) return null;

			return url.GetMediaUrl(item, propertyAlias, cropName, size);
		}
		/// <summary>
		/// Gets the URL of the file in the upload field with the given property alias on the given TypedEntity at the specific size
		/// bsed on: Umbraco.Cms.Web.UrlHelperExtensions
		/// </summary>
		/// <param name="url">The URL.</param>
		/// <param name="entity">The entity.</param>
		/// <param name="propertyAlias">The property alias.</param>
		/// <param name="cropName">The cropName (if set then size must be zero).</param>
		/// <param name="size">The size (must be a prevalue on the upload property editor).</param>
		/// <returns></returns>
		public static string GetMediaUrl(this UrlHelper url, TypedEntity entity, string propertyAlias, string cropName, int size)
		{
			string _url = GetMediaUrl(entity, propertyAlias, cropName, size);
			if (String.IsNullOrEmpty(_url))
				return "";
			else
				return url.Content(_url);
		}
		
		#endregion
	}
}
